/*! \file textarea.cpp		
	This contains the implementation of the TextArea class
*/

#include "textarea.h"
#include "image.h"
#include "guiclass.h"
#include "container.h"
#include "scrollpanel.h"
TextArea::TextArea( Component* parent ) :
	TextComponent( parent )
{
	scroll = 0;
	setWidth( 100 );
}


void TextArea::setWidth( int newW ) {
	// Set the basic widths
	if ( newW < 50 ) newW = 50;
	w = newW;
	widthWithoutBorder = w - 2 * borderWidth;
	
	// we'll need to redo the entire newline map
	setText( buffer ); 
	
	// Update the listeners with an onSize event
	resized();
}

void TextArea::setTextHelper( string text ) {
	GUI* gui = GUI::getInstance();
	Font* font = gui->getFont();
	// 'breakLine' represents where to break this line into a new one
	int breakLine;
	// lastPosition was the last spot a newline was created
	int lastPosition = 0;
	// This is a pixel-measurement to see if we need to make a newline
	int widthOnThisLine = 0;
	for ( int i = 0; i < text.length(); i ++ ) {
		widthOnThisLine += font->letters[(int)text[i]].advancex;
		// If there is a newline, then break the line right there. OR,
		// if the text so far goes beyond the end of this component, then we need to go back
		// through the string and find the first space.
		if ( text[i] == '\n' || widthOnThisLine >= widthWithoutBorder ) {
			bool found = false;
			// Break immediately upon finding a newline
			if ( text[i] == '\n' ) {
				found = true;
				breakLine = i;
			} else {
				// Start searching for a good place to break from the current position
				for ( breakLine = i; breakLine > lastPosition; breakLine-- ) {
					// A space is the best place to break, since it means we don't cut off words
					if ( buffer[breakLine] == ' ' ) {
						found = true;
						break;
					}
				}
			}
			// So if we found a space, set 'breakLine' to be the index of the next character
			// (the character on the next line)
			if ( found ) {
				breakLine = breakLine + 1;
			} else {
				// No space found, so cut off our string right before the end of the textarea
				// NOTE: This means you will be splitting a word in the middle
				breakLine = i - 1;
			}
			// Add the line of text to textRows
			textRows.push_back( text.substr( lastPosition, breakLine - lastPosition ) );
			// Set a new 'lastPosition'
			lastPosition = breakLine;
			// buffer[breakLine] is now the first letter in the next line, so we set our 
			// current width to that
			widthOnThisLine = font->letters[(int)buffer[breakLine]].advancex;
			// And continue from this first character
			i = breakLine;
		}
	}
	// Add the remaining text to textRows
	textRows.push_back( text.substr( lastPosition ) );
	
	h = textRows.size() * font->getMaxAdvanceY();
	// Update the listeners with an onSize event
	resized();
}

void TextArea::appendText( string text ) {
	// Add a newline before the text
	buffer += "\n" + text;
	setTextHelper( text );
}

void TextArea::setText( string text ) {
	// Replace what we had in the buffer
	buffer = text;
	// Clear out textRows
	textRows.clear();
	setTextHelper( buffer );
}

void TextArea::resized() {
	// Tell the parent that this component changed size
	((Container*)parent)->childChangedSize( this );
	
	// Send an onSize event to any listeners
	vector<Listener*>::iterator j;
	for ( j = listeners.begin(); j != listeners.end(); ++j ) {
		(*j)->onSize( Event( this ) );
	}
}

void TextArea::draw() {
	Font* font = GUI::getInstance()->getFont();
	int screenX = getScreenX(), screenY = getScreenY();
	
	GUI::getInstance()->drawRectangle( w, h, bgColorTop, bgColorBottom );
	
	glColor4f( 0.0f, 0.0f, 0.0f, 1.0f );
	//~ cout << font->getMaxAdvanceY() << endl;
	int visibleTextLines = parent->getHeight() / font->getMaxAdvanceY() + 2;
	scroll = ((Container*)(parent))->getScrollPosition() / font->getMaxAdvanceY();
	//~ cout << "Scroll: " << scroll << " Visible: " << visibleTextLines << " Size of vec " << textRows.size() << endl;
	for ( int i = scroll; i < scroll + visibleTextLines; i ++ ) {
		if ( i >= textRows.size() ) break;
		string thisLine = textRows.at( i );
		font->writeString( thisLine, borderWidth, ( (i+1) * font->getMaxAdvanceY() ) - font->getMaxAdvanceY() / 2 );	
	}
	
	if ( border ) {
		ImageHandler::getInstance()->guiBorder( sideID1, cornerID1, screenX, screenY, w, h );
	}
}
